#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/time.h>
#include "Mochila.h"

using namespace std;

double diff(struct timeval *a, struct timeval *b)
{
  return
    (double)(a->tv_sec + (double)a->tv_usec/1000000) -
    (double)(b->tv_sec + (double)b->tv_usec/1000000);
}

void estadisticas(Mochila &m, int num){
  struct timeval ts1,ts2;
   double secs;
    ofstream fs2("estadisticas.txt");
    int x[4] = {10,15,20,22};
    for (int i = 0; i < 4;i++){
         m.generaInstanciaDirecta(x[i]);
         fs2<<"####################### "<<x[i]<<" elementos #######################\n";
         fs2<<"   TAMAÑO MOCHILA ---> "<<m.P()<<endl;
         fs2<<"-----> HEURISTICA POR PESO <-----\n";
         gettimeofday(&ts1,NULL);
         m.heuristicaPeso();
         gettimeofday(&ts2,NULL);
         secs = diff(&ts2,&ts1);
         fs2<<"TIEMPO: "<<secs<<endl;
         fs2<<"valor:" <<m.valorTotal()<<" peso:" <<m.pesoTotal()<<endl;
      
         fs2<<"-----> HEURISTICA POR VALOR <-----\n";
         gettimeofday(&ts1,NULL);
         m.heuristicaValor();
         gettimeofday(&ts2,NULL);
         secs = diff(&ts2,&ts1);
         fs2<<"TIEMPO: "<<secs<<endl;
         fs2<<"valor:" <<m.valorTotal()<<" peso:" <<m.pesoTotal()<<endl;
      
         fs2<<"-----> HEURISTICA POR VALOR/PESO <-----\n";
         gettimeofday(&ts1,NULL);
         m.heuristicaValorPeso();
         gettimeofday(&ts2,NULL);
         secs = diff(&ts2,&ts1);
         fs2<<"TIEMPO: "<<secs<<endl;
         fs2<<"valor:" <<m.valorTotal()<<" peso:" <<m.pesoTotal()<<endl;
      
         fs2<<"-----> ALGORITMO EXACTO <-----\n";
         gettimeofday(&ts1,NULL);
         m.exacto();
         gettimeofday(&ts2,NULL);
         secs = diff(&ts2,&ts1);
         fs2<<"TIEMPO: "<<secs<<endl;
         fs2<<"valor:" <<m.valorTotal()<<" peso:" <<m.pesoTotal()<<endl; 

         fs2<<"-----> ALGORITMO EXACTO CON PODA <-----\n";
         gettimeofday(&ts1,NULL);
         m.exactoPoda();
         gettimeofday(&ts2,NULL);
         secs = diff(&ts2,&ts1);
         fs2<<"TIEMPO: "<<secs<<endl;
         fs2<<"valor:" <<m.valorTotal()<<" peso:" <<m.pesoTotal()<<endl; 

    }
   fs2.close();
}

int main() {
   Mochila m;
   char opcion;
   string fich;
   int num=0, numElementos=5;
   srand((unsigned)time(0));
   while(opcion != '0'){
      cout<<"  +----------------------------------------------------------+"<<endl;
      cout<<"  |             PROBLEMA DE LA MOCHILA                       |"<<endl;
      cout<<"  |      1) Generar ficheros aleatorios                      |"<<endl;
      cout<<"  |      2) Carga ficheros                                   |"<<endl;
      cout<<"  |      3) Heuristica Pesos                                 |"<<endl;
      cout<<"  |      4) Heuristica Valores                               |"<<endl;
      cout<<"  |      5) Heuristica Valor/Peso                            |"<<endl;
      cout<<"  |      6) Algoritmo Exacto                                 |"<<endl<<endl;
      cout<<"  |      7) Estadísticas                                     |"<<endl<<endl;
      cout<<"  |      8) Muestra objetos                                  |"<<endl<<endl;
      cout<<"  |      0) Salir                                            |"<<endl;
      cout<<"  +----------------------------------------------------------+"<<endl;
      cin >> opcion;
      switch(opcion){
         case '1':
               cout<<"Numero de ficheros a generar aleatoriamente: "<<endl;
               cin>>num;
               cout<<"Numero de elementos: "<<endl;
               cin>>numElementos;
               for (int i = 0; i < num;i++){
                  ofstream fs((string("a")+(char)('0'+i)+".txt").c_str());
                  m.generaInstancia(fs,numElementos);
                  fs.close();
               }
               break;
         case '2':
               cout<<"Nombre del fichero a cargar: ";
               cin>>fich;
               cout<<endl;
               m.cargaFichero(fich);
               break;
         case '3': m.muestraObjetos();
                  m.heuristicaPeso();
                 // m.objetosMochila();
               break;
         case '4': m.muestraObjetos();
                  m.heuristicaValor();
                  //m.objetosMochila();
               break;
         case '5': m.muestraObjetos();
                  m.heuristicaValorPeso();
                  //m.objetosMochila();
               break;
         case '6': m.muestraObjetos();
                   m.exacto();
                  // m.objetosMochila();
               break;
         case '7': estadisticas(m,4);
               break;
         case '8': m.muestraObjetos();
               break;
      
      }
   }
   return 0;
}
